const PENDING = "pending"; //等待状态
const FULFILLED = 'fulfilled';// 成功状态
const REJECTED = 'rejected';// 失败状态  
class MyPromise {
    constructor(executor) {
        // 判断是否有错误逻辑
        try {
            // 执行构造器
            executor(this.resolve, this.reject);
        } catch (err) {
            // 抛出错误
            this.reject(err)
        }
    }

    // 当前执行状态默认为等待
    status = PENDING;
    // 默认值为空
    value = undefined;
    // 默认错误原因为空
    reason = undefined;
    // 执行成功回调函数队列
    sucessCallback = [];
    // 执行失败回调函数队列
    fulfilledCallback = [];

    // 成功执行操作
    resolve = (value) => {
        // 判断是否为等待状态,如果不是则return
        if (this.status != PENDING) return
        // 修改状态为成功
        this.status = FULFILLED;
        // 修改value值为传入的值
        this.value = value;
        // 循环执行成功回调函数队列直到数组为空
        while (this.sucessCallback.length) this.sucessCallback.shift()(this.value)
    }

    // 失败时执行操作
    reject = (err) => {
        // 判断是否为等待状态,如果不是则return
        if (this.status != PENDING) return
        // 修改状态为失败
        this.status = REJECTED;
        // 修改value值为传入的错误原因
        this.reason = err;
        // 循环执行失败回调函数队列直到数组为空
        while (this.fulfilledCallback.length) this.fulfilledCallback.shift()(this.reason)

    }

    // then函数
    then(sucessCallback, fulfilledCallback) {
        // 参数可选
        sucessCallback = sucessCallback ? sucessCallback : value => value;
        // 参数可选
        fulfilledCallback = fulfilledCallback ? fulfilledCallback : reason => { throw reason };
        // 执行时返回一个Promise函数方便下一步可以继续使用then函数调用
        let promise2 = new MyPromise((resolve, reject) => {
            // 当状态为成功时执行成功函数处理
            if (this.status == FULFILLED) {
                // 防止外部执行函数中有异步任务时处理
                setTimeout(() => {
                    try {
                        let v = sucessCallback && sucessCallback(this.value);
                        resolvePromise(promise2, v, resolve, reject);
                    } catch (err) {
                        reject(err)
                    }
                }, 0)

            } else if (this.status == REJECTED) {// 当状态为成功时执行成功函数处理
                // 防止外部执行函数中有异步任务时处理
                setTimeout(() => {
                    try {
                        let v = fulfilledCallback && fulfilledCallback(this.reason);
                        resolvePromise(promise2, v, resolve, reject);
                    } catch (err) {
                        reject(err)
                    }
                }, 0)
            } else {
                // 当状态为等待时将传入的成功函数和失败函数存入函数队列当中 
                this.sucessCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let v = sucessCallback && sucessCallback(this.value);
                            resolvePromise(promise2, v, resolve, reject);
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                });
                this.fulfilledCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let v = fulfilledCallback && fulfilledCallback(this.reason);
                            resolvePromise(promise2, v, resolve, reject);
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                });
            }
        })
        // 返回一个Promise对象
        return promise2;
    }

    finally(callback) {
        return this.then(value => {
            return MyPromise.resolve(callback()).then(() => value);
        }, reason => {
            return MyPromise.resolve(callback()).then(() => { throw reason })
        })
    }

    //等同于reject
    catch(fulfilledCallback) {
        return this.then(undefined, fulfilledCallback)
    }

    static all(arr) {
        let result = [];
        let index = 0;
        return new MyPromise((resolve, reject) => {
            // 将值存入数组中
            function addData(key, value) {
                result[key] = value;
                index++;
                // 当数组循环完成调用resolve方法将值全部返回出去
                if (index >= arr.length) {
                    resolve(result);
                }
            }
            // 循环数组
            for (let i = 0; i < arr.length; i++) {
                let current = arr[i];
                // 判断当前值是否为Promise对象，如果是则在then方法中将值抽出来
                if (current instanceof MyPromise) {
                    current.then(value => addData(i, value), err => console.log(err))
                } else {
                    //普通值直接存入数组
                    addData(i, arr[i]);
                }
            }
        })
    }

    static resolve(value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise((resolve) => resolve(value))
    }

}

function resolvePromise(promise2, x, resolve, reject) {
    // 判断当前传入的Promise对象是否为本身
    if (promise2 === x) {
        return reject(new TypeError('不能循环调用'));
    }
    // 判断当前传入的值是否为MyPromise对象
    if (x instanceof MyPromise) {
        x.then(resolve, reject)
    } else {
        resolve(x)
    }
}

